package com.glp.work.flow.contract.builder;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.core.NestedIOException;

import com.glp.work.flow.contract.builder.Table.Cell;
import com.glp.work.flow.contract.builder.Table.Part;

@SuppressWarnings("unchecked")
public class ContractBuilder {

  public List<ContractSource> build(InputStream is) throws Exception {
    SAXReader reader = new SAXReader();
    Document doc = reader.read(new InputStreamReader(is, "UTF-8"));
    Element root = (Element) doc.getRootElement();
    
    List<ContractSource> sources = new ArrayList<ContractSource>();
    for (Element element : (List<Element>) root.elements()) {
      ContractSource source = new ContractSource();
      source.setId(element.attributeValue("id"));
      source.setCode(element.attributeValue("code"));
      source.setName(element.attributeValue("name"));
      source.setTemplate(element.attributeValue("template"));
      
      List<Element> elements = element.elements();
      List<Mark> marks = new ArrayList<Mark>(elements.size());
      for(Element markElement : elements) {
        
        Mark mark = parseMark(markElement);
        marks.add(mark);
      }
      source.setMarks(marks);
      sources.add(source);
    }
    return sources;
  }
  
  private Mark parseMark(Element markElement) throws Exception {
    String name = markElement.attributeValue("name");
    String fontFamily = markElement.attributeValue("font-family");
    String fontSize = markElement.attributeValue("font-size");
    String color = markElement.attributeValue("color");
    String bold = markElement.attributeValue("bold");
    String italic = markElement.attributeValue("italic");
    String evl = markElement.attributeValue("evl");
    String value = markElement.attributeValue("value");
    
    Mark mark = new Mark();
    mark.setName(name);
    mark.setFontFamily(fontFamily);
    mark.setFontSize(StringUtils.isBlank(fontSize) ? null : Integer.parseInt(fontSize));
    mark.setColor(color);
    mark.setBold(StringUtils.isBlank(bold) ? false : Boolean.parseBoolean(bold));
    mark.setItalic(StringUtils.isBlank(italic) ? false : Boolean.parseBoolean(italic));
    mark.setEvl(evl);
    mark.setValue(value);
    
    List<Element> tables = markElement.elements();
    if(!CollectionUtils.isEmpty(tables)) {
      Element tableElement = tables.get(0);
      Table table = parseTable(tableElement);
      mark.setTable(table);
    }
    return mark;
  }
  
  private Table parseTable(Element tableElement) throws Exception {
    String width = tableElement.attributeValue("width");
    String fontFamily = tableElement.attributeValue("font-family");
    String fontSize = tableElement.attributeValue("font-size");
    String color = tableElement.attributeValue("color");
    String bold = tableElement.attributeValue("bold");
    String italic = tableElement.attributeValue("italic");
    
    Table table = new Table();
    table.setWidth(StringUtils.isBlank(width) ? null : Integer.parseInt(width));
    table.setFontFamily(fontFamily);
    table.setFontSize(StringUtils.isBlank(fontSize) ? null : Integer.parseInt(fontSize));
    table.setColor(color);
    table.setBold(StringUtils.isBlank(bold) ? null : Boolean.parseBoolean(bold));
    table.setItalic(StringUtils.isBlank(italic) ? null : Boolean.parseBoolean(italic));
    
    List<Element> parts = tableElement.elements();
    if(!CollectionUtils.isEmpty(parts)) {
      for(Element part : parts) {
        String name = part.getName();
        if("header".equals(name)) {
          table.setHeader(getPart(part));
        } else if("body".equals(name)) {
          table.setBody(getPart(part));
        } else if("footer".equals(name)) {
          table.setFooter(getPart(part));
        } else {
          throw new NestedIOException("Error contract xml. Element table node '" + name + "'");
        }
      }
    }
    return table;
  }
  
  public Part getPart(Element element) {
    String height = element.attributeValue("height");
    String fontFamily = element.attributeValue("font-family");
    String fontSize = element.attributeValue("font-size");
    String color = element.attributeValue("color");
    String bold = element.attributeValue("bold");
    String italic = element.attributeValue("italic");
    String key = element.attributeValue("key");
    
    Part part = new Part();
    part.setHeight(StringUtils.isBlank(height) ? null : Integer.parseInt(height));
    part.setFontFamily(fontFamily);
    part.setFontSize(StringUtils.isBlank(fontSize) ? null : Integer.parseInt(fontSize));
    part.setColor(color);
    part.setBold(StringUtils.isBlank(bold) ? null : Boolean.parseBoolean(bold));
    part.setItalic(StringUtils.isBlank(italic) ? null : Boolean.parseBoolean(italic));
    part.setKey(key);
    
    List<Element> cells = element.elements();
    if(!CollectionUtils.isEmpty(cells)) {
      List<Cell> list = new ArrayList<Cell>(cells.size());
      for (Element cellElement : cells) {
        String width = cellElement.attributeValue("width");
        String eFontFamily = element.attributeValue("font-family");
        String eFontSize = element.attributeValue("font-size");
        String eColor = element.attributeValue("color");
        String eBold = element.attributeValue("bold");
        String eItalic = element.attributeValue("italic");
        String evl = cellElement.attributeValue("evl");
        String value = cellElement.attributeValue("value");
        
        Cell cell = new Cell();
        cell.setWidth(StringUtils.isBlank(width) ? null : Integer.parseInt(width));
        cell.setFontFamily(eFontFamily);
        cell.setFontSize(StringUtils.isBlank(eFontSize) ? null : Integer.parseInt(eFontSize));
        cell.setColor(eColor);
        cell.setBold(StringUtils.isBlank(eBold) ? null : Boolean.parseBoolean(eBold));
        cell.setItalic(StringUtils.isBlank(eItalic) ? null : Boolean.parseBoolean(eItalic));
        cell.setEvl(evl);
        cell.setValue(value);
        
        list.add(cell);
      }
      part.setCells(list);
    }
    return part;
  }
}